﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace UtilityToolsCollectInStandard.ToolsCollection
{
    public class XamlUtilityTools
    {
        public static IEnumerable<T> GetChilds<T>(DependencyObject SourceElement) where T : DependencyObject
        {
            Queue<DependencyObject> CacheQueue = new Queue<DependencyObject>();
            CacheQueue.Enqueue(SourceElement);
            DependencyObject Current;
            int Count;
            while (CacheQueue.Count > 0)
            {
                Current = CacheQueue.Dequeue();
                if (Current is T Result)
                    yield return Result;
                Count = VisualTreeHelper.GetChildrenCount(Current);
                while (Count-- > 0)
                    CacheQueue.Enqueue(VisualTreeHelper.GetChild(Current, Count));
            }
            yield break;
        }

        public static bool GetParent<T>(DependencyObject SourceElement, out T? Result) where T : DependencyObject
        {
            DependencyObject current = SourceElement;
            Result = null;
            while (current != null)
            {
                if (current is T Parent)
                {
                    Result = Parent;
                    return true;
                }
                try { current = VisualTreeHelper.GetParent(current); }
                catch { return false; }
            }
            return false;
        }

        public static IEnumerable<DependencyObject> GetChildsByTypeName(DependencyObject SourceElement, string TarTypeName)
        {
            Queue<DependencyObject> CacheQueue = new Queue<DependencyObject>();
            CacheQueue.Enqueue(SourceElement);
            DependencyObject Current;
            int Count;
            while (CacheQueue.Count > 0)
            {
                Current = CacheQueue.Dequeue();
                if (Current.GetType().Name.Equals(TarTypeName, StringComparison.OrdinalIgnoreCase))
                    yield return Current;
                Count = VisualTreeHelper.GetChildrenCount(Current);
                while (Count-- > 0)
                    CacheQueue.Enqueue(VisualTreeHelper.GetChild(Current, Count));
            }
            yield break;
        }

        public static Window GetVisualElementParentWindow(DependencyObject dependencyObject) => Window.GetWindow(dependencyObject);

        public static bool GetVisualElementOfParent<T>(DependencyObject dependencyObject, out T? Result) where T : DependencyObject
        {
            Result = null;
            while (dependencyObject != null)
            {
                if (dependencyObject is T TValue)
                {
                    Result = TValue;
                    return true;
                }
                dependencyObject = VisualTreeHelper.GetParent(dependencyObject);
            }
            return false;
        }
        public static bool GetVisualElementInChilds<T>(DependencyObject dependencyObject, out T? Result) where T : DependencyObject
        {
            Result = null;
            HashSet<DependencyObject> Cache = new HashSet<DependencyObject>();
            Cache.Add(dependencyObject);
            while (Cache.Count > 0)
            {
                dependencyObject = Cache.First();
                Cache.Remove(dependencyObject);
                if (dependencyObject is T TValue)
                {
                    Result = TValue;
                    return true;
                }
                GetVisualElementInChilds(dependencyObject, Cache);
            }
            return false;
        }
        public static bool GetVisualElementInChilds(DependencyObject dependencyObject, HashSet<DependencyObject> Result)
        {
            if (Result == null)
                Result = new HashSet<DependencyObject>();
            if (dependencyObject == null)
                return false;
            int count = VisualTreeHelper.GetChildrenCount(dependencyObject);
            if (count < 1)
                return false;
            for (int i = 0; i < count; i++)
                Result.Add(VisualTreeHelper.GetChild(dependencyObject, i));
            return true;
        }
    }
}
